{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "ffe42cdf",
   "metadata": {},
   "source": [
    "# tf.keras.Model\n",
    "\n",
    "模型类\n",
    "\n",
    "```python\n",
    "tf.keras.Model(*args, **kwargs)\n",
    "```\n",
    "- inpts: tf.keras.Input 定义的输入，可以是数组\n",
    "- outputs: 网络的输出，可以是数组\n",
    "- name: string, 模型名称\n",
    "\n",
    "\n",
    "tf = 2.9.1\n",
    "\n",
    "\n",
    "**属性**\n",
    "\n",
    "- model.layers  # 包含的layers\n",
    "- model.metrics_names  # 训练时，需要计算的指标\n",
    "\n",
    "**方法**\n",
    "\n",
    "- call(inputs, training=None, mask=None)  \n",
    "- compile(optimizer, loss, metrics, loss_weights, weighted_metrics, ...,)\n",
    "- compute_loss(x=None, y=None, y_pred=None, ...)\n",
    "- evaluate(...)\n",
    "- fit(...)\n",
    "- get_layer(name=None, index=None)\n",
    "- predict(x, ...,)\n",
    "- predict_on_batch(...)\n",
    "- predict_step()\n",
    "- reset_metrics()\n",
    "- save(filepath)\n",
    "- save_spec(...)\n",
    "- save_weights(filepath, overwrite=True, save_format=None, options=None)\n",
    "- summary(...)\n",
    "- test_on_batch(...)\n",
    "- test_step(...)\n",
    "- to_json(...)\n",
    "- to_yaml(...)\n",
    "- train_on_batch(...)\n",
    "- train_step()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ca61ff7a",
   "metadata": {},
   "source": [
    "```python\n",
    "call(inputs, training=None, mask=None)\n",
    "\n",
    "compile(\n",
    "    optimizer='rmsprop',\n",
    "    loss=None,\n",
    "    metrics=None,\n",
    "    loss_weights=None,\n",
    "    weighted_metrics=None,\n",
    "    run_eagerly=None,\n",
    "    steps_per_execution=None,\n",
    "    jit_compile=None,\n",
    "    **kwargs\n",
    ")\n",
    "\n",
    "compute_loss(\n",
    "    x=None, y=None, y_pred=None, sample_weight=None\n",
    ")\n",
    "\n",
    "evaluate(\n",
    "    x=None,\n",
    "    y=None,\n",
    "    batch_size=None,\n",
    "    verbose='auto',\n",
    "    sample_weight=None,\n",
    "    steps=None,\n",
    "    callbacks=None,\n",
    "    max_queue_size=10,\n",
    "    workers=1,\n",
    "    use_multiprocessing=False,\n",
    "    return_dict=False,\n",
    "    **kwargs\n",
    ")\n",
    "\n",
    "fit(\n",
    "    x=None,\n",
    "    y=None,\n",
    "    batch_size=None,\n",
    "    epochs=1,\n",
    "    verbose='auto',\n",
    "    callbacks=None,\n",
    "    validation_split=0.0,\n",
    "    validation_data=None,\n",
    "    shuffle=True,\n",
    "    class_weight=None,\n",
    "    sample_weight=None,\n",
    "    initial_epoch=0,\n",
    "    steps_per_epoch=None,\n",
    "    validation_steps=None,\n",
    "    validation_batch_size=None,\n",
    "    validation_freq=1,\n",
    "    max_queue_size=10,\n",
    "    workers=1,\n",
    "    use_multiprocessing=False\n",
    ")\n",
    "\n",
    "get_layer(\n",
    "    name=None, index=None\n",
    ")\n",
    "\n",
    "predict(\n",
    "    x,\n",
    "    batch_size=None,\n",
    "    verbose='auto',\n",
    "    steps=None,\n",
    "    callbacks=None,\n",
    "    max_queue_size=10,\n",
    "    workers=1,\n",
    "    use_multiprocessing=False\n",
    ")\n",
    "\n",
    "save(\n",
    "    filepath,\n",
    "    overwrite=True,\n",
    "    include_optimizer=True,\n",
    "    save_format=None,\n",
    "    signatures=None,\n",
    "    options=None,\n",
    "    save_traces=True\n",
    ")\n",
    "\n",
    "save_spec(\n",
    "    dynamic_batch=True\n",
    ")\n",
    "\n",
    "save_weights(\n",
    "    filepath, overwrite=True, save_format=None, options=None\n",
    ")\n",
    "\n",
    "summary(\n",
    "    line_length=None,\n",
    "    positions=None,\n",
    "    print_fn=None,\n",
    "    expand_nested=False,\n",
    "    show_trainable=False\n",
    ")\n",
    "\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "8cb42011",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'2.9.1'"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import tensorflow as tf\n",
    "\n",
    "tf.__version__"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fe6a5de8",
   "metadata": {},
   "source": [
    "## 例子"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "78650d72",
   "metadata": {},
   "source": [
    "### 1.采用 inputs, outputs的方式"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "58c799eb",
   "metadata": {},
   "outputs": [],
   "source": [
    "import tensorflow as tf\n",
    "\n",
    "inputs = tf.keras.Input(shape=(None, None, 3))  # [batch, width, height, channel]\n",
    "# 对维度进行裁剪，默认裁剪第2、3维度  输入为[batch, width, height, channel]\n",
    "processed = tf.keras.layers.RandomCrop(width=32, height=32)(inputs)  # [batch, 32, 32, channel]\n",
    "# 进行卷积操作 输出2层特征层，卷积核3x3 \n",
    "conv = tf.keras.layers.Conv2D(filters=2, kernel_size=3)(processed)  # [batch, 30, 30, 2]\n",
    "# 全局池化，在第2、3维度进行全局池化操作\n",
    "pooling = tf.keras.layers.GlobalAveragePooling2D()(conv)  # [batch, 2]\n",
    "# 全连接层\n",
    "feature = tf.keras.layers.Dense(10)(pooling)  # [batch, 10]\n",
    "\n",
    "full_model = tf.keras.Model(inputs, feature)\n",
    "backbone = tf.keras.Model(processed, conv)\n",
    "activations = tf.keras.Model(conv, feature)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4e0491fb",
   "metadata": {},
   "source": [
    "### 2.继承Model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "id": "ead2ae0b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "TensorShape([32, 100, 22, 5])"
      ]
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import tensorflow as tf\n",
    "\n",
    "class MyModel(tf.keras.Model):\n",
    "    def __init__(self):\n",
    "        super().__init__()\n",
    "        self.dense1 = tf.keras.layers.Dense(4, activation=tf.nn.relu)\n",
    "        self.dense2 = tf.keras.layers.Dense(5, activation=tf.nn.softmax)\n",
    "        \n",
    "    def call(self, inputs):  # [batch, ..., n_dim]\n",
    "        x = self.dense1(inputs)  # [batch, ..., 4]\n",
    "        x = self.dense2(x)  # [batch, ..., 5]\n",
    "        return x\n",
    "    \n",
    "model = MyModel()\n",
    "\n",
    "import numpy as np\n",
    "i = np.random.random((32, 100, 22, 44))\n",
    "o = model(i)\n",
    "o.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "id": "83051f98",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "TensorShape([32, 100, 22, 5])"
      ]
     },
     "execution_count": 54,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 区别训练和推理的处理\n",
    "\n",
    "import tensorflow as tf\n",
    "\n",
    "class MyModel(tf.keras.Model):\n",
    "    def __init__(self):\n",
    "        super().__init__()\n",
    "        self.dense1 = tf.keras.layers.Dense(4, activation=tf.nn.relu)\n",
    "        self.dense2 = tf.keras.layers.Dense(5, activation=tf.nn.softmax)\n",
    "        self.dropout = tf.keras.layers.Dropout(0.5)\n",
    "    \n",
    "    def call(self, inputs, training=False):  # [batch, ..., n_dim]\n",
    "        x = self.dense1(inputs)  # [batch, ..., 4]\n",
    "        x = self.dense2(x)  # [batch, ..., 5]\n",
    "        if training:\n",
    "            x = self.dropout(x)\n",
    "        return x\n",
    "    \n",
    "model = MyModel()\n",
    "import numpy as np\n",
    "i = np.random.random((32, 100, 22, 44))\n",
    "o = model(i, training=True)\n",
    "o.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f14ff1cd",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "32424f65",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "edfb010c",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0c38f92c",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b8290a8c",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "56bc5dfd",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6812ab88",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7c63aa67",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "72c38110",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b5141508",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8c938bda",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
